package com.woniu.repaircenter.service.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Snowflake;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.woniu.exception.XinanException;
import com.woniu.exception.repaircenter.RepairException;
import com.woniu.repaircenter.models.dto.RepairDTO;
import com.woniu.repaircenter.models.dto.RepairListDTO;
import com.woniu.repaircenter.models.param.*;
import com.woniu.repaircenter.service.mapper.RepairMapper;
import com.woniu.repaircenter.service.model.Repair;
import com.woniu.repaircenter.service.service.*;
import com.woniu.user.client.UserFeignClient;
import com.woniu.user.dto.EmployeeNameDTO;
import com.woniu.utils.EnumException; // 引入异常枚举
import com.woniu.utils.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

import static java.lang.System.currentTimeMillis;
import static java.lang.System.setOut;

/**
 * <p>
 * 维修记录表 服务实现类
 * </p>
 *
 * @author 吕雨泽
 * @since 2024年12月06日
 */
@Service
public class RepairServiceImpl extends ServiceImpl<RepairMapper, Repair> implements RepairService {

    @Autowired
    private RepairMapper repairMapper;

    @Autowired
    private RepairLogService repairLogService;

    @Autowired
    private RepairFileUploadService repairFileUploadService;

    @Autowired
    private RepairCategoryService repairCategoryService;

    @Resource
    UserFeignClient userFeignClient;

    /**
     * 添加维修工单
     *
     * @param arp 添加维修工单参数
     * @return 添加结果
     * @throws XinanException 异常
     */
    @Override
    @Transactional
    public Integer addRepair(AddRepairParam arp, String userId) throws Exception, LinkageError {
        // 生成维修工单号
        String repairNum = new Snowflake(1, 1).nextIdStr();
        String appointmentTime = arp.getAppointmentTime();
        // 定义日期格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        // 将字符串转换为 Date 对象
        Date appointmentTimeDate = sdf.parse(appointmentTime);

        // 将 Date 对象转换为时间戳（毫秒）
        long timestamp = appointmentTimeDate.getTime();

        // 验证预约时间是否有效
        if (timestamp < currentTimeMillis()) {
            throw new LinkageError("预约时间不能小于当前时间");
        }
        if (arp.getRepairCategoryId() == null || arp.getRepairCategoryId() == 0) {
            throw new RepairException(EnumException.INVALID_PARAMETER);
        }
        // 将添加维修工单参数转换为维修对象
        Repair repair = BeanUtil.toBean(arp, Repair.class);
        repair.setRepairUser(userId);
        // 处理维修照片
        handleRepairPhotos(arp, repairNum, repair);
        // 设置维修工单状态为待审核
        repair.setRepairState(0);
        //设置维修类别名称
        String repairContent = repairCategoryService.selectById(arp.getRepairCategoryId());
        repair.setRepairType(repairContent);

        //设置维修地址repairArea
        Result<String> areaCodeName = userFeignClient.getAreaCodeById(Integer.parseInt(arp.getRepairArea()));
        if (areaCodeName.getCode() == 200) {
            repair.setRepairInfo(areaCodeName.getData());
        } else {
            throw new RepairException(EnumException.INVALID_PARAMETER);
        }
        // 设置维修工单号
        repair.setRepairNum(repairNum);
        // 设置创建用户
        repair.setCreateUser(arp.getRepairUserName());
        // 设置创建日期
        repair.setCreateDate(formatCurrentDateTime());
        // 设置未删除状态
        repair.setDeleted(0);
        // 添加维修工单
        Integer result = repairMapper.addRepair(repair);
        // 如果添加成功
        if (result != 0) {
            // 记录维修工单生成待审核日志
            logRepairAction(repairNum, "0", "维修工单生成，待审核", repair.getCreateUser() + "于" + repair.getCreateDate() + "创建维修工单", repair.getRepairUser());
        }
        // 返回添加结果
        return result;
    }

    /**
     * 查询维修工单列表
     *
     * @param srp 查询参数，包含分页信息和查询条件
     * @return 维修工单列表，包含分页信息
     * @throws RepairException 当查询过程中发生异常时抛出
     */
    @Override
    public PageInfo<RepairListDTO> selectRepairList(SelectRepairParam srp) throws RepairException {
        // 验证查询参数的有效性
        validateSelectRepairParam(srp);
        // 启动分页功能，根据查询参数中的页码和页面大小进行分页
        PageHelper.startPage(srp.getPageNum(), srp.getPageSize());
        // 将查询参数转换为Repair对象，用于后续的查询操作
        Repair selectRepair = BeanUtil.toBean(srp, Repair.class);
        // 设置维修工单的状态信
        // 调用Mapper方法查询维修工单列表
        List<RepairListDTO> repairDTOS = repairMapper.selectRepairList(srp);
        // 将查询结果封装为 PageInfo 对象，用于返回分页信息
        PageInfo<RepairListDTO> repairListDTOS = new PageInfo<>(repairDTOS);
        Result<List<EmployeeNameDTO>> listResult = userFeignClient.selectEmployeeInfo();
        if (listResult.getCode() != 200) {
            throw new RepairException(EnumException.INVALID_PARAMETER);
        }
        for (RepairListDTO repairListDTO : repairListDTOS.getList()) {
            if (repairListDTO.getRepairPerson() != null) {
                for (EmployeeNameDTO datum : listResult.getData()) {
                    if (repairListDTO.getRepairPerson().equals(datum.getUserId())) {
                        repairListDTO.setRepairPersonName(datum.getUserName());
                    }
                }
            }
        }
        // 设置维修工单的状态信息
        setRepairStates(repairListDTOS.getList());
        // 返回封装好的维修工单列表
        return repairListDTOS;
    }

    /**
     * 根据维修单ID和维修单编号选择维修记录
     *
     * @param repairId  维修单ID，用于数据库查询
     * @param repairNum 维修单编号，用于数据库查询
     * @return 包含维修单详细信息的RepairDTO对象，包括维修日志和照片
     * @throws XinanException 如果维修单ID或编号无效，或者查询过程中发生错误
     */
    @Override
    public RepairDTO selectRepairById(Long repairId, String repairNum) throws XinanException {
        // 验证维修单ID和编号的有效性
        validateRepairIdAndNum(repairId, repairNum);
        // 通过ID和编号从数据库中选择维修记录
        RepairDTO repairDTO = repairMapper.selectRepairById(repairId, repairNum);
        if (repairDTO == null) {
            // 如果未找到匹配的维修记录，抛出异常
            throw new XinanException(EnumException.REPAIR_NOT_FOUND);
        }
        if (repairDTO.getRepairPerson() != null) {
            Result<List<EmployeeNameDTO>> listResult = userFeignClient.selectEmployeeInfo();
            if (listResult.getCode() == 200) {
                for (EmployeeNameDTO datum : listResult.getData()) {
                    if (repairDTO.getRepairPerson().equals(datum.getUserId())) {
                        repairDTO.setRepairPersonName(datum.getUserName());
                    }
                }
            } else {
                throw new RepairException(EnumException.INVALID_PARAMETER);
            }
        }
        // 设置维修DTO的状态和描述信息
        setRepairStateAndDescription(repairDTO);
        //返回填充了详细信息的维修DTO
        return repairDTO;
    }

    /**
     * 重写删除维修工单的方法
     *
     * @param repairNum 维修工单编号，用于标识特定的维修记录
     * @return 返回影响的行数，表示删除操作的结果
     * @throws Exception 如果发生错误，抛出异常
     */
    @Override
    public Integer deleteRepair(String repairNum, String userId, String userName) throws Exception {
        // 验证维修工单编号的有效性
        validateRepairNum(repairNum);
        // 根据维修工单编号查询维修记录
        Repair repair = repairMapper.selectRepairByNum(repairNum);
        if (!userId.equals(repair.getRepairUser())) {
            // 如果未找到匹配的维修记录，抛出异常
            throw new XinanException(EnumException.REPAIR_NOT_FOUND);
        }
        // 验证维修记录的存在性和状态
        validateRepair(repair);
        // 标记维修记录为已删除
        repair.setDeleted(1);
        // 更新维修记录
        Integer result = repairMapper.updateRepair(repair);
        // 如果更新成功，记录维修工单删除的操作日志
        if (result != 0) {
            logRepairAction(repairNum, String.valueOf(repair.getRepairState()), "维修工单删除", "删除维修工单", userName);
        }
        // 返回更新结果
        return result;
    }

    /**
     * 分配维修工单给维修人员
     *
     * @param udrf      包含维修工单号和分配的维修人员信息的参数对象
     * @param adminName 执行分配操作的管理员用户名
     * @return 返回更新操作影响的行数
     * @throws Exception 如果操作过程中发生错误，则抛出异常
     */
    @Override
    public Integer dispatchRepair(UpdateDispatchRepairParam udrf, String adminName) throws Exception {
        Result result = userFeignClient.updateWorkerInfoStatus(udrf.getRepairPerson());
        if (result.getCode() != 200) {
            throw new RepairException(EnumException.INVALID_PARAMETER);
        }
        Result<List<EmployeeNameDTO>> listResult = userFeignClient.selectEmployeeInfo();
        if (listResult.getCode() != 200) {
            throw new RepairException(EnumException.INVALID_PARAMETER);
        }
        for (EmployeeNameDTO datum : listResult.getData()) {
            if (udrf.getRepairPerson().equals(datum.getUserId())) {
                udrf.setRepairPersonName(datum.getUserName());
            }
        }
        // 验证维修工单号的有效性
        validateRepairNum(udrf.getRepairNum());
        // 根据维修工单号查询维修工单信息
        Repair repair = repairMapper.selectRepairByNum(udrf.getRepairNum());
        // 验证维修工单的整体有效性
        validateRepair(repair);
        // 检查维修工单的状态是否允许分配
        validateRepairState(repair, 0);
        // 审核人员
        repair.setOneAuditlUser(adminName);
        // 更新维修工单的状态为已分配，并指定维修人员
        updateRepairStateAndPerson(repair, udrf.getRepairPerson(), 1);
        // 记录分配维修工单的操作日志
        logRepairAction(repair.getRepairNum(), "1", "维修工单分配", adminName + "分配该维修工单给" + udrf.getRepairPersonName(), adminName);
        // 更新数据库中的维修工单信息，并返回影响的行数
        return repairMapper.updateRepair(repair);
    }

    /**
     * 更新维修工单状态为进行中
     *
     * @param repairNum 维修工单编号
     * @param userName  操作用户名
     * @return 更新影响的行数
     * @throws Exception 如果更新过程中发生错误，则抛出异常
     */
    @Override
    public Integer underwayRepair(String repairNum, String userName) throws Exception {
        // 调用更新维修工单状态的方法，将状态从1更新为2，表示维修工单正在执行中
        return updateRepairState(repairNum, userName, 1, 2, "维修工单进行中", "开始维修");
    }

    /**
     * 完成维修工单
     *
     * @param ufrp     维修工单号，用于标识特定的维修工单
     * @param userName 用户名，用于记录完成维修工单的用户
     * @return 返回更新操作的结果，通常是一个表示操作状态的整数
     * @throws Exception 如果更新过程中发生错误，抛出此异常
     */
    @Override
    public Integer finishRepair(UpdateFinishRepairParam ufrp, String userName) throws Exception {
        // 调用updateRepairState方法更新维修工单状态为已完成，
        // 其中2和3是状态代码，"维修工单已完成"和"完成该维修订单"是状态描述
        // 将照片ID数组转换为集合，以去除重复项
        if (ufrp.getRepairPhotoIds() != null && ufrp.getRepairPhotoIds().length > 0) {
            Set<Integer> set = new HashSet<>(Arrays.asList(ufrp.getRepairPhotoIds()));
            // 调用文件上传服务，上传照片
            Integer uploadedCount = repairFileUploadService.addFileUpload(set, ufrp.getRepairNum());
            // 检查上传的照片数量是否与提供的照片ID数量一致
            if (uploadedCount != set.size()) {
                // 如果数量不一致，抛出上传失败异常
                throw new RepairException(EnumException.UPLOAD_FAILED);
            }
        }


        return updateRepairState(ufrp.getRepairNum(), userName, 2, 3, "维修工单已完成", "完成该维修订单用时：");
    }

    /**
     * 驳回维修工单
     *
     * @param bean      包含驳回维修工单所需信息的参数对象，包括维修工单编号和驳回描述
     * @param adminName 执行驳回操作的管理员用户名，用于记录操作者信息
     * @return 返回执行结果，通常用于表示驳回操作是否成功
     * @throws Exception 如果驳回操作过程中发生错误，抛出异常
     */
    @Override
    public Integer rejectRepair(UpdateRejectRepairParam bean, String adminName) throws Exception {
        // 调用更新维修工单状态和描述的方法，设置维修工单为驳回状态
        // 参数包括维修工单编号、操作者用户名、工单状态码、处理结果码、处理结果标题和具体描述
        // 状态码0表示工单为驳回状态，处理结果码4表示驳回操作
        return updateRepairStateWithDescription(bean.getRepairNum(), adminName, 0, 4, "维修工单驳回", "驳回该维修工单原因：" + bean.getDescription());
    }

    /**
     * 取消维修工单
     *
     * @param bean     包含维修工单号和取消描述的参数对象
     * @param userName 操作取消的用户名
     * @return 返回更新操作的影响行数
     * @throws Exception 如果更新过程中发生错误，则抛出异常
     */
    @Override
    public Integer cancelRepair(UpdateRejectRepairParam bean, String userName) throws Exception {
        // 调用方法更新维修工单的状态为已取消，并提供取消原因
        return updateRepairStateWithDescription(bean.getRepairNum(), userName, 0, 5, "维修工单取消", "取消该维修工单原因：" + bean.getDescription());
    }

    /**
     * 根据工人信息选择维修单
     *
     * @param bean 包含工人信息和分页参数的查询条件对象
     * @return 返回维修单列表的分页信息
     * @throws Exception 如果查询过程中发生错误，则抛出异常
     */
    @Override
    public PageInfo<RepairListDTO> selectRepairByWorker(SelectRepairWorkerParam bean, String userId) throws Exception {
        // 调用getRepairList方法获取维修单列表的分页信息
        return getRepairList(bean, bean.getPageNum(), bean.getPageSize(), userId, null);
    }

    /**
     * 根据用户ID选择维修记录
     *
     * @param bean 包含查询参数的对象，如用户ID，页码和页面大小等
     * @return 返回一个包含维修列表DTO的PageInfo对象，用于分页展示维修记录
     * @throws Exception 如果查询过程中发生错误，此方法将抛出异常，交由调用者处理
     */
    @Override
    public PageInfo<RepairListDTO> selectRepairByUserId(SelectRepairUserParam bean, String userId) throws Exception {
        // 调用getRepairList方法获取维修列表，参数包括查询参数对象，页码和页面大小
        return getRepairList(bean, bean.getPageNum(), bean.getPageSize(), null, userId);
    }

    /**
     * 处理维修照片
     *
     * @param arp       维修参数对象，包含维修照片ID数组
     * @param repairNum 维修记录编号
     * @param repair    维修对象
     * @throws XinanException 如果上传照片失败，抛出维修异常
     */
    private void handleRepairPhotos(AddRepairParam arp, String repairNum, Repair repair) throws XinanException {
        // 检查是否有维修照片ID提供
        if (arp.getRepairPhotoIds() != null && arp.getRepairPhotoIds().length > 0) {
            // 获取维修照片ID数组
            Integer[] ids = arp.getRepairPhotoIds();
            // 将照片ID数组转换为集合，以去除重复项
            Set<Integer> set = new HashSet<>(Arrays.asList(ids));
            // 调用文件上传服务，上传照片
            Integer uploadedCount = repairFileUploadService.addFileUpload(set, repairNum);
            // 检查上传的照片数量是否与提供的照片ID数量一致
            if (uploadedCount != set.size()) {
                // 如果数量不一致，抛出上传失败异常
                throw new RepairException(EnumException.UPLOAD_FAILED);
            }
        }
    }

    /**
     * 验证选择维修参数对象的有效性
     *
     * @param srp 选择维修参数对象，包含页码和页面大小等信息
     * @throws RepairException 如果参数无效，抛出维修异常
     */
    private void validateSelectRepairParam(SelectRepairParam srp) throws RepairException {
        // 检查srp对象是否为空，以及页码和页面大小是否为有效值
        if (srp == null || srp.getPageNum() < 1 || srp.getPageSize() < 1) {
            // 如果任何参数无效，抛出无效参数异常
            throw new RepairException(EnumException.INVALID_PARAMETER);
        }
    }

    /**
     * 验证维修单ID和编号的有效性
     *
     * @param repairId  维修单ID，用于数据库中的唯一标识
     * @param repairNum 维修单编号，用于用户界面展示
     * @throws RepairException 如果维修单ID或编号为空，或ID为负数，抛出维修异常，指示参数无效
     */
    private void validateRepairIdAndNum(Long repairId, String repairNum) throws RepairException {
        // 检查维修单ID和编号是否为null或空，以及ID是否为负数
        if (repairId == null || repairNum == null || repairId < 0 || repairNum.isEmpty()) {
            // 如果任何参数无效，抛出异常
            throw new RepairException(EnumException.INVALID_PARAMETER);
        }
    }

    /**
     * 验证维修记录的有效性
     *
     * @param repair 维修记录对象，用于验证其有效性
     * @throws RepairException 如果维修记录为空或已被删除，则抛出此异常
     */
    private void validateRepair(Repair repair) throws RepairException {
        // 检查维修记录是否为空
        if (repair == null) {
            throw new RepairException(EnumException.REPAIR_NOT_FOUND);
        }
        // 检查维修记录是否已被标记为删除
        if (repair.getDeleted() == 1) {
            throw new RepairException(EnumException.REPAIR_DELETED);
        }
    }

    /**
     * 验证维修编号是否有效
     *
     * @param repairNum 维修编号，需要验证的字符串
     * @throws RepairException 如果维修编号为空或无效，抛出维修异常
     */
    private void validateRepairNum(String repairNum) throws RepairException {
        // 检查维修编号是否为null或空，如果是，则抛出异常
        if (repairNum == null || repairNum.isEmpty()) {
            throw new RepairException(EnumException.INVALID_PARAMETER);
        }
    }

    /**
     * 验证维修单的状态是否符合预期
     *
     * @param repair        维修单对象，包含维修相关信息和状态
     * @param expectedState 期望的维修状态码，用于比较当前状态是否符合预期
     * @throws RepairException 如果当前维修单的状态与预期状态不符，抛出此异常
     */
    private void validateRepairState(Repair repair, int expectedState) throws RepairException {
        // 检查维修单的当前状态是否与预期状态相等
        if (repair.getRepairState() != expectedState) {
            // 如果状态不符，抛出维修异常，表示维修单状态异常
            throw new RepairException(EnumException.ORDER_STATE_EXCEPTION);
        }
    }

    /**
     * 更新维修单的维修人员和维修状态
     *
     * @param repair       维修单对象，包含需要更新的维修单信息
     * @param repairPerson 新的维修人员姓名，用于替换当前维修单中的维修人员
     * @param repairState  新的维修状态，用于替换当前维修单中的维修状态
     */
    private void updateRepairStateAndPerson(Repair repair, String repairPerson, int repairState) {
        // 设置新的维修人员
        repair.setRepairPerson(repairPerson);
        // 设置新的维修状态
        repair.setRepairState(repairState);
    }

    /**
     * 更新维修工单的状态和时间
     *
     * @param repair      维修工单对象，包含需要更新的维修信息
     * @param repairState 新的维修状态，用于更新维修工单的当前状态
     */
    private void updateRepairStateAndTime(Repair repair, int repairState) {
        // 设置维修工单的新状态
        repair.setRepairState(repairState);
        // 设置维修工单的维修时间，确保时间信息的实时更新
        if (repairState == 2) {
            // 如果维修状态为2（进行中），则设置维修时间为当前时间
            repair.setRepairTime(formatCurrentDateTime());
        } else if (repairState == 3) {
            // 如果维修状态为3（完成），则设置维修时间为当前时间
            repair.setCompleteDate(formatCurrentDateTime());
        }
    }

    /**
     * 更新维修单的状态和描述信息
     *
     * @param repair      维修单对象，代表需要更新的维修单实例
     * @param repairState 新的维修状态，用于更新维修单的当前状态
     * @param description 新的描述信息，用于详细说明维修单的状况或进展
     */
    private void updateRepairStateAndDescription(Repair repair, int repairState, String description) {
        // 更新维修单的状态
        repair.setRepairState(repairState);
        // 更新维修单的描述信息
        repair.setDescription(description);
    }

    /**
     * 计算维修所花费的时间
     *
     * @param repair 维修对象，包含维修时间和完成日期等信息
     */
    private void calculateRepairTakeTime(Repair repair) {
        // 确保维修时间和完成日期都不为空，以进行后续的时间差计算
        if (repair.getRepairTime() != null && repair.getCompleteDate() != null) {
            // 定义日期时间格式，用于解析字符串到LocalDateTime对象
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            // 移除维修时间字符串中的毫秒部分，确保时间格式与数据库保持一致
            String repairTime = repair.getRepairTime().replaceAll("\\.0$", "");
            repair.setRepairTime(repairTime);
            // 将字符串形式的维修开始时间和完成时间转换为LocalDateTime对象
            LocalDateTime startLocalDateTime = LocalDateTime.parse(repairTime, formatter);
            LocalDateTime endLocalDateTime = LocalDateTime.parse(repair.getCompleteDate(), formatter);
            // 将LocalDateTime转换为ZonedDateTime，以考虑时区信息
            ZonedDateTime startZonedDateTime = startLocalDateTime.atZone(ZoneId.systemDefault());
            ZonedDateTime endZonedDateTime = endLocalDateTime.atZone(ZoneId.systemDefault());
            // 计算维修所花费的时间，单位为毫秒
            long repairTakeTimeMillis = endZonedDateTime.toInstant().toEpochMilli() - startZonedDateTime.toInstant().toEpochMilli();
            // 将花费时间转换为分钟，并设置到Repair对象中
            repair.setRepairTakeTime(repairTakeTimeMillis / 1000 / 60 + "分钟");
        }
    }

    /**
     * 记录维修操作日志
     *
     * @param repairNum   维修单号，用于标识特定的维修任务
     * @param repairState 维修状态，表示维修任务当前的状态
     * @param operName    操作人姓名，记录执行操作的人员
     * @param operReason  操作原因，描述进行该操作的具体原因
     * @param userName    用户名，通常与操作人一致，用于关联日志与特定用户
     * @throws XinanException 当日志记录操作失败时，抛出此异常
     */
    private void logRepairAction(String repairNum, String repairState, String operName, String operReason, String userName) throws XinanException {
        // 创建一个新的插入维修日志参数对象
        InsertRepairLogParam irlp = new InsertRepairLogParam();
        // 设置维修日志的维修单号
        irlp.setRepairNum(repairNum);
        // 设置维修日志的维修状态
        irlp.setRepairState(repairState);
        // 设置维修日志的操作人姓名
        irlp.setOperName(operName);
        // 设置维修日志的操作原因
        irlp.setOperReason(operReason);
        // 调用维修日志服务的插入方法，记录维修操作日志
        repairLogService.insertRepairLog(irlp, userName);
    }

    /**
     * 设置维修状态和描述信息
     *
     * @param repairDTO 维修DTO对象，包含维修相关信息
     */
    private void setRepairStateAndDescription(Object repairDTO) {
        if (repairDTO instanceof RepairListDTO) {
            RepairListDTO repairListDTO = (RepairListDTO) repairDTO;
            // 根据维修状态代码设置维修状态字符串
            switch (repairListDTO.getRepairState()) {
                case 0:
                    repairListDTO.setState("待审核");
                    break;
                case 1:
                    repairListDTO.setState("已分配");
                    break;
                case 2:
                    repairListDTO.setState("维修中");
                    break;
                case 3:
                    repairListDTO.setState("维修完成");
                    break;
                case 4:
                    repairListDTO.setState("已驳回");
                    break;
                case 5:
                    repairListDTO.setState("已取消");
                    break;
                default:
                    repairListDTO.setState("未知状态");
                    break;
            }
            // 根据删除状态代码设置删除状态字符串
            switch (repairListDTO.getDeleted()) {
                case 0:
                    repairListDTO.setDeleteDetails("未删除");
                    break;
                case 1:
                    repairListDTO.setDeleteDetails("已删除");
                    break;
                default:
                    repairListDTO.setDeleteDetails("未知状态");
                    break;
            }
        } else if (repairDTO instanceof RepairDTO) {
            RepairDTO repairDto = (RepairDTO) repairDTO;
            // 根据维修状态代码设置维修状态字符串
            switch (repairDto.getRepairState()) {
                case 0:
                    repairDto.setState("待审核");
                    break;
                case 1:
                    repairDto.setState("已分配");
                    break;
                case 2:
                    repairDto.setState("维修中");
                    break;
                case 3:
                    repairDto.setState("维修完成");
                    break;
                case 4:
                    repairDto.setState("已驳回");
                    break;
                case 5:
                    repairDto.setState("已取消");
                    break;
                default:
                    repairDto.setState("未知状态");
                    break;
            }
            // 根据删除状态代码设置删除状态字符串
            switch (repairDto.getDeleted()) {
                case 0:
                    repairDto.setDeleteDetails("未删除");
                    break;
                case 1:
                    repairDto.setDeleteDetails("已删除");
                    break;
                default:
                    repairDto.setDeleteDetails("未知状态");
                    break;
            }
        }
    }


    /**
     * 设置维修列表中每个维修项的状态和描述信息
     *
     * @param repairListDTOS 维修列表DTO对象的集合，用于展示维修列表信息
     */
    private void setRepairStates(List<RepairListDTO> repairListDTOS) {
        // 遍历维修列表DTO，对每个维修项进行处理
        for (RepairListDTO repairListDTO : repairListDTOS) {
            // 设置维修项的状态和描述信息
            setRepairStateAndDescription(repairListDTO);
        }
    }

    /**
     * 设置维修DTO的状态和描述信息
     *
     * @param repairDTO 维修DTO对象，用于传递维修相关的数据
     */
    private void setRepairStateAndDescription(RepairDTO repairDTO) {
        // 设置维修DTO的状态和描述信息
        setRepairStateAndDescription((Object) repairDTO);
    }

    /**
     * 获取当前日期和时间的格式化字符串
     *
     * @return 当前日期和时间的格式化字符串
     */
    private String formatCurrentDateTime() {
        // 创建一个DateTimeFormatter实例，用于格式化日期和时间
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 获取当前系统日期和时间，并使用formatter进行格式化，然后返回格式化后的字符串
        return LocalDateTime.now().format(formatter);
    }

    /**
     * 更新维修状态
     *
     * @param repairNum     维修工单号，用于标识特定的维修任务
     * @param userName      操作用户名，用于记录谁进行了状态更新操作
     * @param expectedState 预期的当前状态，用于验证维修任务的当前状态是否与预期相符
     * @param newState      新的状态，维修任务将要被更新到的目标状态
     * @param operName      操作名称，描述进行状态变更的操作类型
     * @param operReason    操作原因，解释为什么进行状态变更
     * @return 返回数据库更新操作的结果，通常表示更新是否成功
     * @throws Exception 如果状态更新过程中任何步骤验证失败或出现错误，抛出异常
     */
    private Integer updateRepairState(String repairNum, String userName, int expectedState, int newState, String operName, String operReason) throws Exception {
        // 验证维修工单号是否有效
        validateRepairNum(repairNum);
        // 根据工单号获取维修记录
        Repair repair = repairMapper.selectRepairByNum(repairNum);
        // 验证维修记录本身是否有效
        validateRepair(repair);
        // 验证维修记录的当前状态是否与预期相符
        validateRepairState(repair, expectedState);
        // 更新维修状态和时间
        updateRepairStateAndTime(repair, newState);
        String operReason1 = userName + "：" + operReason;
        // 如果新状态为3，计算维修所花费的时间
        if (newState == 3) {
            calculateRepairTakeTime(repair);
            operReason1 = userName + "：" + operReason + "，维修花费时间：" + repair.getRepairTakeTime();
        }
        // 记录维修操作日志
        logRepairAction(repairNum, String.valueOf(newState), operName, operReason1, userName);
        // 更新数据库中的维修记录并返回更新结果
        return repairMapper.updateRepair(repair);
    }

    /**
     * 更新维修状态并添加操作描述
     *
     * @param repairNum     维修编号，用于识别特定的维修记录
     * @param userName      操作用户名，记录谁进行了此次状态更新
     * @param expectedState 预期的当前状态，用于验证维修记录的当前状态是否与此值相符
     * @param newState      新的状态，维修记录将被更新为这个状态
     * @param operName      操作名称，描述此次状态变更的操作类型
     * @param operReason    操作原因，解释为何进行此次状态更新
     * @return 返回更新影响的行数，通常为1表示成功更新
     * @throws Exception 如果验证失败或数据库操作出错，抛出异常
     */
    private Integer updateRepairStateWithDescription(String repairNum, String userName, int expectedState, int newState, String operName, String operReason) throws Exception {
        // 验证维修编号的有效性
        validateRepairNum(repairNum);
        // 根据维修编号查询维修记录
        Repair repair = repairMapper.selectRepairByNum(repairNum);
        // 验证维修记录是否存在
        validateRepair(repair);
        // 验证维修记录的当前状态是否符合预期的更新状态
        validateRepairState(repair, expectedState);
        // 更新维修记录的状态和描述信息
        updateRepairStateAndDescription(repair, newState, operReason);
        // 记录维修操作日志
        logRepairAction(repairNum, String.valueOf(newState), operName, operReason, userName);
        // 执行数据库更新操作并返回影响的行数
        return repairMapper.updateRepair(repair);
    }

    /**
     * 获取维修列表信息
     *
     * @param bean     查询条件对象，包含需要查询的维修信息参数
     * @param pageNum  页码，表示请求的页面编号
     * @param pageSize 页面大小，表示每页显示的记录数
     * @return 返回包含维修列表信息的PageInfo对象
     * @throws Exception 如果查询过程中发生错误，则抛出异常
     */
    private PageInfo<RepairListDTO> getRepairList(Object bean, int pageNum, int pageSize, String repairPerson, String repairUser) throws Exception {
        Result<List<EmployeeNameDTO>> listResult = userFeignClient.selectEmployeeInfo();
        if (listResult.getCode() != 200) {
            throw new RepairException(EnumException.INVALID_PARAMETER);
        }
        // 启用分页功能，指定当前页码和页面大小
        PageHelper.startPage(pageNum, pageSize);
        // 将查询条件对象转换为Repair对象，以便进行数据库查询
        Repair selectRepair = BeanUtil.toBean(bean, Repair.class);
        selectRepair.setRepairPerson(repairPerson);
        selectRepair.setRepairUser(repairUser);
        // 调用Mapper方法，查询符合查询条件的维修列表信息
        List<RepairListDTO> repairListDTOS = repairMapper.selectRepair(selectRepair);
        // 设置维修状态信息，对查询结果列表中的每个维修项进行状态处理
        setRepairStates(repairListDTOS);
        // 创建并初始化PageInfo对象，用于封装分页查询结果
        PageInfo<RepairListDTO> pageInfo = new PageInfo<>(repairListDTOS);
        for (RepairListDTO repairListDTO : pageInfo.getList()) {
            // 设置维修人员姓名
            if (repairListDTO.getRepairPerson() != null) {
                for (EmployeeNameDTO datum : listResult.getData()) {
                    if (repairListDTO.getRepairPerson().equals(datum.getUserId())) {
                        repairListDTO.setRepairPersonName(datum.getUserName());
                    }
                }
            }
        }
        // 返回封装好的分页信息对象
        return pageInfo;
    }
}
